﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using ProjectBase.Core;

using System.Collections.Specialized;
using System.Web.Mvc;

namespace $safeprojectname$.Core.Mvc
{
    [TestClass]
    public class SmartBinder_MultiTest : EntityTestBase<Facade>
    {
        [TestMethod]
        public void BindValueTypes()
        {
            var filter = new DummyBindingFilter();

            Binder.Bind(filter, ValueProvider.ToContainer());

            AssertStandard(filter, FormatProvider);
            AssertLists(filter, FormatProvider);
        }

        #region protected

        private static NameValueCollection FillValueProvider(CultureInfo formatProvider)
        {
            var nameValueCollection = new NameValueCollection();

            nameValueCollection.Add("Codes", "c1");
            nameValueCollection.Add("Codes", "c2");
            nameValueCollection.Add("Codes", "null");
            nameValueCollection["Code"] = "c*";

            nameValueCollection.Add("Descriptions", "d1");
            nameValueCollection.Add("Descriptions", "d2");
            nameValueCollection.Add("Descriptions", "d3");
            nameValueCollection.Add("Descriptions", "null");
            nameValueCollection["Description"] = "*a*";

            nameValueCollection.Add("Ages", 10.ToString(formatProvider));
            nameValueCollection.Add("Ages", 15.ToString(formatProvider));
            nameValueCollection.Add("Ages", 20.ToString(formatProvider));
            nameValueCollection.Add("Ages", "null");

            nameValueCollection["Age"] = 10.ToString(formatProvider);
            nameValueCollection["AgeFrom"] = 5.ToString(formatProvider);
            nameValueCollection["AgeTo"] = 100.ToString(formatProvider);

            nameValueCollection.Add("Validitys", new DateTime(2000, 1, 1).ToString(formatProvider));
            nameValueCollection.Add("Validitys", new DateTime(1999, 12, 31).ToString(formatProvider));
            nameValueCollection.Add("Validitys", new DateTime(2000, 1, 2).ToString(formatProvider));
            nameValueCollection.Add("Validitys", "null");

            nameValueCollection["Validity"] = new DateTime(2000, 1, 2).ToString(formatProvider);
            nameValueCollection["ValidityFrom"] = new DateTime(1999, 11, 11).ToString(formatProvider);
            nameValueCollection["ValidityTo"] = new DateTime(2000, 12, 31).ToString(formatProvider);

            nameValueCollection.Add("IsVisibles", true.ToString(formatProvider));
            nameValueCollection.Add("IsVisibles", "null");

            nameValueCollection["IsVisible"] = true.ToString(formatProvider);
            nameValueCollection["IsVisibleFrom"] = false.ToString(formatProvider);
            nameValueCollection["IsVisibleTo"] = true.ToString(formatProvider);

            nameValueCollection.Add("Salarys", 1000.05M.ToString(formatProvider));
            nameValueCollection.Add("Salarys", 999.7M.ToString(formatProvider));
            nameValueCollection.Add("Salarys", 1001M.ToString(formatProvider));
            nameValueCollection.Add("Salarys", "null");

            nameValueCollection["Salary"] = 1000M.ToString(formatProvider);
            nameValueCollection["SalaryFrom"] = 998M.ToString(formatProvider);
            nameValueCollection["SalaryTo"] = 1002M.ToString(formatProvider);

            return nameValueCollection;
        }

        protected virtual void AssertLists(DummyBindingFilter filter, CultureInfo formatProvider)
        {
            foreach (var value in Collection.GetValues("Codes"))
            {
                Assert.IsTrue(filter.Codes.Contains(value), "Codes {0}", value);
            }
            foreach (var value in Collection.GetValues("Descriptions"))
            {
                Assert.IsTrue(filter.Descriptions.Contains(value), "Descriptions {0}", value);
            }
            foreach (var value in Collection.GetValues("Ages"))
            {
                var toString = filter.Ages.Select(i => i.IsNull() ? "null" : i.ToDisplay(formatProvider: formatProvider));
                Assert.IsTrue(toString.Contains(value), "Ages {0}", value);
            }
            foreach (var value in Collection.GetValues("Salarys"))
            {
                var toString = filter.Salarys.Select(i => i.IsNull() ? "null" : i.ToDisplay(formatProvider: formatProvider));
                Assert.IsTrue(toString.Contains(value), "Salarys {0}", value);
            }
            foreach (var value in Collection.GetValues("IsVisibles"))
            {
                var toString = filter.IsVisibles.Select(i => i.IsNull() ? "null" : i.ToDisplay(formatProvider: formatProvider));
                Assert.IsTrue(toString.Contains(value), "IsVisibles {0}", value);
            }
            foreach (var value in Collection.GetValues("Validitys"))
            {
                var toString = filter.Validitys.Select(i => i.IsNull() ? "null" : i.ToDisplay(formatProvider: formatProvider));
                Assert.IsTrue(toString.Contains(value), "Validitys {0}", value);
            }
        }

        protected virtual void AssertStandard(DummyBindingFilter filter, CultureInfo formatProvider)
        {
            Assert.AreEqual(filter.Code.ToDisplay(formatProvider: formatProvider), Collection["Code"], "{0}, {1}".FormatWith(filter.Code.ToDisplay(formatProvider: formatProvider), Collection["Code"]));
            Assert.AreEqual(filter.Description.ToDisplay(formatProvider: formatProvider), Collection["Description"], "{0}, {1}".FormatWith(filter.Description.ToDisplay(formatProvider: formatProvider), Collection["Description"]));
            Assert.AreEqual(filter.Age.ToDisplay(formatProvider: formatProvider), Collection["Age"], "{0}, {1}".FormatWith(filter.Age.ToDisplay(formatProvider: formatProvider), Collection["Age"]));
            Assert.AreEqual(filter.AgeFrom.ToDisplay(formatProvider: formatProvider), Collection["AgeFrom"], "{0}, {1}".FormatWith(filter.AgeFrom.ToDisplay(formatProvider: formatProvider), Collection["AgeFrom"]));
            Assert.AreEqual(filter.AgeTo.ToDisplay(formatProvider: formatProvider), Collection["AgeTo"], "{0}, {1}".FormatWith(filter.AgeTo.ToDisplay(formatProvider: formatProvider), Collection["AgeTo"]));
            Assert.AreEqual(filter.Validity.ToDisplay(formatProvider: formatProvider), Collection["Validity"], "{0}, {1}".FormatWith(filter.Validity.ToDisplay(formatProvider: formatProvider), Collection["Validity"]));
            Assert.AreEqual(filter.ValidityFrom.ToDisplay(formatProvider: formatProvider), Collection["ValidityFrom"], "{0}, {1}".FormatWith(filter.ValidityFrom.ToDisplay(formatProvider: formatProvider), Collection["ValidityFrom"]));
            Assert.AreEqual(filter.ValidityTo.ToDisplay(formatProvider: formatProvider), Collection["ValidityTo"], "{0}, {1}".FormatWith(filter.ValidityTo.ToDisplay(formatProvider: formatProvider), Collection["ValidityTo"]));
            Assert.AreEqual(filter.IsVisible.ToDisplay(formatProvider: formatProvider), Collection["IsVisible"], "{0}, {1}".FormatWith(filter.IsVisible.ToDisplay(formatProvider: formatProvider), Collection["IsVisible"]));
            Assert.AreEqual(filter.IsVisibleFrom.ToDisplay(formatProvider: formatProvider), Collection["IsVisibleFrom"], "{0}, {1}".FormatWith(filter.IsVisibleFrom.ToDisplay(formatProvider: formatProvider), Collection["IsVisibleFrom"]));
            Assert.AreEqual(filter.IsVisibleTo.ToDisplay(formatProvider: formatProvider), Collection["IsVisibleTo"], "{0}, {1}".FormatWith(filter.IsVisibleTo.ToDisplay(formatProvider: formatProvider), Collection["IsVisibleTo"]));
            Assert.AreEqual(filter.Salary.ToDisplay(formatProvider: formatProvider), Collection["Salary"], "{0}, {1}".FormatWith(filter.Salary.ToDisplay(formatProvider: formatProvider), Collection["Salary"]));
            Assert.AreEqual(filter.SalaryFrom.ToDisplay(formatProvider: formatProvider), Collection["SalaryFrom"], "{0}, {1}".FormatWith(filter.SalaryFrom.ToDisplay(formatProvider: formatProvider), Collection["SalaryFrom"]));
            Assert.AreEqual(filter.SalaryTo.ToDisplay(formatProvider: formatProvider), Collection["SalaryTo"], "{0}, {1}".FormatWith(filter.SalaryTo.ToDisplay(formatProvider: formatProvider), Collection["SalaryTo"]));
        }

        #endregion protected

        #region Additional test attributes

        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        [TestInitialize]
        public override void MyTestInitialize()
        {
            base.MyTestInitialize(); // Use TestInitialize to run code before running each test

            // get a standard framework binder
            Binder = ProjectBase.Core.Service.Factory.CreateInstance<IObjectBinder>();
            //Binder.ModelBinder = new ImprovedBinder();

            // convert to en
            FormatProvider = CultureInfo.GetCultureInfo("en-us");

            // prefil collection
            Collection = FillValueProvider(FormatProvider);

            ValueProvider = new NameValueCollectionValueProvider(Collection, FormatProvider);
        }

        [TestCleanup]
        public override void MyTestCleanup()
        {
            base.MyTestCleanup(); // Use TestCleanup to run code after each test has run
        }

        #endregion Additional test attributes

        #region shared properties

        protected virtual IObjectBinder Binder { get; set; }

        protected virtual NameValueCollection Collection { get; set; }

        protected virtual IValueProvider ValueProvider { get; set; }

        protected virtual CultureInfo FormatProvider { get; set; }

        #endregion shared properties
    }
}